package cmp.compile.panels;

/*********************************************
 * 	The Add/Edit Window for the species panel
 *  Plus Database chooser class called from the Add database window
 *  
 *  The object is created in the CompilePanel to be displayed in the main panel
 *  DEFAULTS:
 *  		Prefix is initialized in DatabaseSelectPanel
 *  		Filenames are set in FileSelectTextField, except for PROTEINsTCW is setPeptideDB 
 */
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;

import util.ui.UserPrompt;

import cmp.main.Globals;
import cmp.viewer.panels.DatabaseSelectPanel;

public class EditSpeciesPanel extends JPanel {
	private static final long serialVersionUID = -8431928635947256814L;
	private String lastSMAT=null;
	
	public EditSpeciesPanel(CompilePanel parentPanel) {
		theParentPanel = parentPanel;
		setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
		setAlignmentX(Component.CENTER_ALIGNMENT);
		
		mainPanel = createDatabaseSelectPanel();
		mainPanel.setMaximumSize(mainPanel.getPreferredSize());
		mainPanel.setMinimumSize(mainPanel.getPreferredSize());
		mainPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
		
		add(mainPanel);
		
		pnlDBSelect = new DatabaseSelectPanel(Globals.Viewer.DB_NAME_PREFIX, 
		        Globals.Viewer.DB_NAME_PREFIXold, this); 
		pnlDBSelect.setVisible(false);
		
		add(pnlDBSelect);
		
		updateFileSelection();
	}
	
	/************************************ 
	 * Add/Edit window for Species 
	 ***/
	private JPanel createDatabaseSelectPanel() {
		
	/*** For add/edit species window **/
		lblDatabase = new JLabel("singleTCW");
		
		btnSelectDB = new JButton("Select " + Globals.Viewer.DB_NAME_PREFIX + " Database");
		btnSelectDB.setBackground(Globals.MENUCOLOR);
		btnSelectDB.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				mainPanel.setVisible(false);
				pnlDBSelect.setVisible(true);
			}
		});					
	
		lblPrefix = new JLabel("Prefix");
		txtPrefix = new JTextField(15);
		txtPrefix.setMaximumSize(txtPrefix.getPreferredSize());
		txtPrefix.setMinimumSize(txtPrefix.getPreferredSize());
		
		btnUseSMATFile = new JRadioButton("Generate protein file");
		btnUseSMATFile.setBackground(Globals.BGCOLOR);
		btnUseSMATFile.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				updateFileSelection();
			}
		});
		lblSMATFile = new JLabel("SMAT File");
		txtSMATFile = new FileSelectTextField(theParentPanel, 20, CompilePanel.getSMATDirectory(),"smat");
		txtSMATFile.setMaximumSize(txtSMATFile.getPreferredSize());
		txtSMATFile.setMinimumSize(txtSMATFile.getPreferredSize());
		
		btnUseProteinFile = new JRadioButton("Use existing protein file");
		btnUseProteinFile.setBackground(Globals.BGCOLOR);
		btnUseProteinFile.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				updateFileSelection();
			}
		});
		lblProteinFile = new JLabel("Protein File");
		txtProteinFile = new FileSelectTextField(theParentPanel, 20, null,"prot");
		txtProteinFile.setMaximumSize(txtProteinFile.getPreferredSize());
		txtProteinFile.setMinimumSize(txtProteinFile.getPreferredSize());
	
		ButtonGroup group = new ButtonGroup();
		group.add(btnUseSMATFile);
		group.add(btnUseProteinFile);
		
		lblRemark = new JLabel("Remark");
		txtRemark = new JTextField(20);
		txtRemark.setMaximumSize(txtRemark.getPreferredSize());
		txtRemark.setMinimumSize(txtRemark.getPreferredSize());
		
		btnKeep = new JButton("Keep");
		btnKeep.setBackground(Globals.BGCOLOR);
		btnKeep.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				executeKeep();
				
			}
		});
		
		btnDiscard = new JButton("Discard");
		btnDiscard.setBackground(Globals.BGCOLOR);
		btnDiscard.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				setVisible(false);
				theParentPanel.setMainPanelVisible(true);
			}
		});
		
		btnHelp = new JButton("Help");
		btnHelp.setBackground(Globals.HELPCOLOR);
		btnHelp.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				UserPrompt.displayHTMLResourceHelp(theParentPanel.getParentFrame(), 
						"Edit species", "html/runMultiTCW/EditSpeciesPanel.html");
			}
		});
		
		JPanel retVal = CompilePanel.getPanel(false);
		retVal.setAlignmentX(Component.CENTER_ALIGNMENT);

		JPanel row = CompilePanel.getPanel(true);
		row.add(lblDatabase);
		row.add(Box.createHorizontalStrut(Globals.CompilePanel.WIDTH -lblDatabase.getPreferredSize().width));
		row.add(btnSelectDB);
		
		retVal.add(row);
		retVal.add(Box.createVerticalStrut(10));
		
		retVal.add(createSummaryPanel());
		retVal.add(Box.createVerticalStrut(10));
		
		row = CompilePanel.getPanel(true);
		row.add(lblPrefix);
		row.add(Box.createHorizontalStrut(Globals.CompilePanel.WIDTH - lblPrefix.getPreferredSize().width));
		row.add(txtPrefix);
		
		retVal.add(row);
		retVal.add(Box.createVerticalStrut(20));	

		retVal.add(btnUseSMATFile);
		row = CompilePanel.getPanel(true);
		row.add(Box.createHorizontalStrut(10));
		row.add(lblSMATFile);
		row.add(Box.createHorizontalStrut(Globals.CompilePanel.WIDTH - lblSMATFile.getPreferredSize().width));
		row.add(txtSMATFile);
		
		retVal.add(row);
		retVal.add(Box.createVerticalStrut(10));	
		
		retVal.add(btnUseProteinFile);
		row = CompilePanel.getPanel(true);
		row.add(Box.createHorizontalStrut(10));
		row.add(lblProteinFile);
		row.add(Box.createHorizontalStrut(Globals.CompilePanel.WIDTH - lblProteinFile.getPreferredSize().width));
		row.add(txtProteinFile);
		
		retVal.add(row);
		retVal.add(Box.createVerticalStrut(20));	
		
		row = CompilePanel.getPanel(true);
		row.add(lblRemark);
		row.add(Box.createHorizontalStrut(Globals.CompilePanel.WIDTH - lblRemark.getPreferredSize().width));
		row.add(txtRemark);
		
		retVal.add(row);
		retVal.add(Box.createVerticalStrut(10));
		
		JPanel outRow = CompilePanel.getPanel(true);

		row = CompilePanel.getPanel(true);
		row.add(Box.createHorizontalGlue());
		row.add(btnKeep);
		row.add(Box.createHorizontalStrut(10));
		row.add(btnDiscard);
		row.add(Box.createHorizontalStrut(10));
		row.add(btnHelp);
		row.add(Box.createHorizontalGlue());
		
		row.setMaximumSize(row.getPreferredSize());
		row.setMinimumSize(row.getPreferredSize());
		row.setAlignmentX(Component.CENTER_ALIGNMENT);
		
		outRow.add(Box.createHorizontalGlue());
		outRow.add(row);
		outRow.add(Box.createHorizontalGlue());
		retVal.add(outRow);
		
		retVal.setMaximumSize(retVal.getPreferredSize());
		retVal.setMinimumSize(retVal.getPreferredSize());
		
		return retVal;
	}
	// Keep
	private void executeKeep() {
		boolean isValid = true;
		lastSMAT = null;
		boolean isGenerateProteinFile = btnUseSMATFile.isSelected(); 
		boolean isPeptideDB = !btnUseSMATFile.isEnabled(); 
		
		String SMATFile = txtSMATFile.getText().trim(); 
		String SMATPath = SMATFile;
		if (!SMATFile.contains("/")) SMATPath = Globals.Compile.SMATDIR + "/" + SMATFile;
		
		String proteinFile = txtProteinFile.getText().trim(); 
		String proteinPath = proteinFile;
		if (!proteinFile.startsWith("/") ) 
				proteinPath = theParentPanel.getCurProjectDirectory() + proteinFile;
		
		// XXX check if they selected database
		String db = lblDBValue.getText();
		if (db==null || db.trim().equals("")) {
			JOptionPane.showMessageDialog(theParentPanel, "Select sTCW database.",
					"Invalid database", JOptionPane.PLAIN_MESSAGE);
			isValid=false;
		}
		// check prefix
		String prefix = txtPrefix.getText();
		if(prefix.trim().length() > 3) {
			JOptionPane.showMessageDialog(theParentPanel, "Prefix too long (limit 3 characters).",
					"Invalid prefix", JOptionPane.PLAIN_MESSAGE);

			System.err.println("Error: Prefix too long (limit 3 characters)");
			JOptionPane.showMessageDialog(theParentPanel, "Prefix too long (limit 3 characters");
			isValid = false;
		}
		if (!prefix.matches("[\\w\\d]+")) {
			JOptionPane.showMessageDialog(theParentPanel, "Prefix contains invalid characters." +
					"\nUse letters, numbers, and underscores.",
					"Invalid prefix", JOptionPane.PLAIN_MESSAGE);
			System.err.println("Error: prefix contains invalid characters");
			isValid = false;
		}
		if (isValid) {
			int row = -1;
			if(isEditMode()) row = theParentPanel.getSpeciesPanel().getSelectedRow();
			
			for(int x=0; x<theParentPanel.getSpeciesPanel().getNumRows() && isValid; x++) {
				if(x != row && theParentPanel.getSpeciesPanel().getPrefixAt(x).equals(prefix)) {
					System.err.println("Error: duplicate prefix");
					JOptionPane.showMessageDialog(theParentPanel,"Duplicate prefix " + prefix);
					isValid = false;
				}
			}
		}
		// check protein file -- also checked in LoadAAfiles
		if (!isPeptideDB) {		
			if(!isGenerateProteinFile) {
				
				if(proteinFile.length() == 0) {
					System.err.println("Error: No specified protein file");
					JOptionPane.showMessageDialog(theParentPanel, "No specified protein file");
					isValid = false;
				}
				else if(!(new File(proteinPath)).exists()) {	
					if (!proteinFile.equals(Globals.PROTEINsTCW)) {
						System.err.println("Error: protein file does not exist " + proteinPath);
						JOptionPane.showMessageDialog(theParentPanel, "Protein file does not exist " + proteinPath);
						isValid = false;
					}
				}
			}
			if(isGenerateProteinFile) {
				if(SMATFile.trim().length() == 0) {
					System.err.println("Error: No specified SMAT file");
					JOptionPane.showMessageDialog(theParentPanel,"No specified SMAT file");
					isValid = false;
				}
				else if(!(new File(SMATPath)).exists()) {
					System.err.println("Error: SMAT file does not exist " + SMATPath);
					JOptionPane.showMessageDialog(theParentPanel, "SMAT file does not exist " + SMATPath);
					isValid = false;
				}
				if (isValid) lastSMAT = SMATFile;
			}
		}
		if (isValid) {
			String host = lblHostValue.getText(); 
			String dbname = lblDBValue.getText(); 
			String assemName = lblAssemValue.getText();
			String remark = txtRemark.getText(); 
			
			if(isEditMode()) 
				theParentPanel.getSpeciesPanel().setRow(theParentPanel.getSpeciesPanel().getSelectedRow(),
					host, dbname, prefix, assemName, 
					proteinFile, SMATFile, remark, isGenerateProteinFile, isPeptideDB);
			else
				theParentPanel.getSpeciesPanel().addRow(
					host, dbname, prefix, assemName,
					proteinFile, SMATFile, remark, isGenerateProteinFile, isPeptideDB);
			theParentPanel.getSpeciesPanel().updateTable();
			theParentPanel.updateSpeciesRemark(prefix, remark);
			theParentPanel.saveCPAVE();
			setVisible(false);
			theParentPanel.setMainPanelVisible(true);
		}
	}
	/************************************************
	 * Summary information about sTCW database after selected
	 * This is shown under "Select sTCW Database"
	 */
	private JPanel createSummaryPanel() {
		JPanel retVal = CompilePanel.getPanel(false);
		
		lblHostHeader = new JLabel("Host");
		lblHostHeader.setMaximumSize(lblHostHeader.getPreferredSize());
		lblHostHeader.setMinimumSize(lblHostHeader.getPreferredSize());
		lblDBHeader = new JLabel("Database");
		lblDBHeader.setMaximumSize(lblDBHeader.getPreferredSize());
		lblDBHeader.setMinimumSize(lblDBHeader.getPreferredSize());
		lblTypeHeader = new JLabel("Type");
		lblTypeHeader.setMaximumSize(lblTypeHeader.getPreferredSize());
		lblTypeHeader.setMinimumSize(lblTypeHeader.getPreferredSize());
		
		lblHostValue = new JLabel("");
		lblDBValue = new JLabel("");
		lblAssemValue = new JLabel("");
		lblTypeValue = new JLabel("");
		
		JPanel row = CompilePanel.getPanel(true);
		row.add(lblHostHeader);
		if(lblHostHeader.getMaximumSize().width < Globals.CompilePanel.WIDTH)
			row.add(Box.createHorizontalStrut(Globals.CompilePanel.WIDTH - lblHostHeader.getMaximumSize().width));
		row.add(lblHostValue);
		retVal.add(row);
		
		row = CompilePanel.getPanel(true);
		row.add(lblDBHeader);
		if(lblDBHeader.getMaximumSize().width < Globals.CompilePanel.WIDTH)
			row.add(Box.createHorizontalStrut(Globals.CompilePanel.WIDTH - lblDBHeader.getMaximumSize().width));
		row.add(lblDBValue);
		retVal.add(row);
					
		row = CompilePanel.getPanel(true);
		row.add(lblTypeHeader);
		if(lblTypeHeader.getMaximumSize().width < Globals.CompilePanel.WIDTH)
			row.add(Box.createHorizontalStrut(Globals.CompilePanel.WIDTH - lblTypeHeader.getMaximumSize().width));
		row.add(lblTypeValue);
		retVal.add(row);
					
		return retVal;
	}
	
	public void setMainPanelVisible(boolean visible) {
		mainPanel.setVisible(visible);
	}
		
	public void setHost(String host) { lblHostValue.setText(host); }
	
	public void setPeptideDB(boolean isPep) {
		if(lblHostValue.getText().length() > 0 || lblDBValue.getText().length() > 0) {
			lblTypeValue.setText(isPep?"Protein":"Nucleotide");
			if (isPep) txtProteinFile.setText(Globals.PROTEINsTCW); 
		}
		else
			lblTypeValue.setText("");
		txtProteinFile.setEnabled(!isPep);
		lblProteinFile.setEnabled(!isPep);
		txtSMATFile.setEnabled(!isPep);
		lblSMATFile.setEnabled(!isPep);
		btnUseSMATFile.setEnabled(!isPep);
		btnUseProteinFile.setEnabled(!isPep);
	} 
	// following are called from the Species panel of the main panel on 
	// Add or Edit to pass in values
	public void setDBName(String dbName) { lblDBValue.setText(dbName); } 
	public void setAssemblyName(String assembly) { lblAssemValue.setText(assembly); }
	public void setProteinFile(String aaFile) { txtProteinFile.setText(aaFile); }
	public void setSMATFile(String SMATFile) {txtSMATFile.setText(SMATFile); }
	public void setRemark(String remark) { txtRemark.setText(remark); }
	public void setPrefix(String prefix) { txtPrefix.setText(prefix); }
	public void setGenerateProteinFile(boolean isSMAT) {
		btnUseSMATFile.setSelected(isSMAT);
		btnUseProteinFile.setSelected(!isSMAT);
		updateFileSelection();
	}
	public void setGenerateProteinFile() { 
		if (lastSMAT!=null) {
			btnUseSMATFile.setSelected(true);
			btnUseProteinFile.setSelected(false);
			txtSMATFile.setText(lastSMAT);
		}
		else {
			btnUseSMATFile.setSelected(false);
			btnUseProteinFile.setSelected(true);
		}
		updateFileSelection();
	}	
	public boolean isEditMode() { return bEditMode; }
	public void setEditMode(boolean mode) { bEditMode = mode; }
	
	public boolean isLoaded() { return bLoaded; }
	public void setLoaded(boolean loaded) { 
		bLoaded = loaded;
		
		lblDatabase.setEnabled(!loaded);
		btnSelectDB.setEnabled(!loaded);
		lblProteinFile.setEnabled(!loaded);
		txtProteinFile.setEnabled(!loaded);
		lblSMATFile.setEnabled(!loaded);
		txtSMATFile.setEnabled(!loaded);
		btnUseSMATFile.setEnabled(!loaded);
		btnUseProteinFile.setEnabled(!loaded);
		lblPrefix.setEnabled(!loaded);
		txtPrefix.setEnabled(!loaded);
		lblHostHeader.setEnabled(!loaded);
		lblDBHeader.setEnabled(!loaded);
		lblTypeHeader.setEnabled(!loaded);
		
		lblHostValue.setEnabled(!loaded);
		lblDBValue.setEnabled(!loaded);
		lblAssemValue.setEnabled(!loaded);
		lblTypeValue.setEnabled(!loaded);
	}
	
	public void updateFileSelection() {
		//Is a peptide database/do nothing if disabled
		if(!btnUseSMATFile.isEnabled() && !btnUseProteinFile.isEnabled()) {
			return;
		}
		txtProteinFile.setEnabled(!btnUseSMATFile.isSelected());
		txtSMATFile.setEnabled(btnUseSMATFile.isSelected());
	}
	
	//Database select
	private CompilePanel theParentPanel = null;
	private JPanel mainPanel = null;
	private JLabel lblDatabase = null;
	private JButton btnSelectDB = null;
	private JButton btnKeep = null;
	private JButton btnDiscard = null;
	private JButton btnHelp = null;
	private DatabaseSelectPanel pnlDBSelect = null;
	private JLabel lblProteinFile = null;
	private FileSelectTextField txtProteinFile = null;
	private JLabel lblSMATFile = null;
	private FileSelectTextField txtSMATFile = null;
	private JRadioButton btnUseSMATFile = null;
	private JRadioButton btnUseProteinFile = null;
	private JLabel lblRemark = null;
	private JTextField txtRemark = null;
	private JLabel lblPrefix = null;
	private JTextField txtPrefix = null;
	
	//Summary JLabels for assembly
	private JLabel lblHostHeader = null;
	private JLabel lblDBHeader = null;
	private JLabel lblTypeHeader = null;
	
	private JLabel lblHostValue = null;
	private JLabel lblDBValue = null;
	private JLabel lblAssemValue = null;
	private JLabel lblTypeValue = null;
	
	private boolean bEditMode = false;
	private boolean bLoaded = false;
}
